package com.springsecurity.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.session.HttpSessionEventPublisher;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	@Autowired
	private SecurityUserDetailsService userDetailsService;
	
	@Autowired
	private AjaxAuthenticationSuccessHandler successHandler;
	
	@Autowired
    private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
	
	@Autowired
	private MyAccessDeniedHandler accessDeniedHandler;
	
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	
	/**
     	* 配置密码编码器，Spring Security 5.X必须配置，否则登录时报空指针异常
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    //并发session控制
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 加入自定义的安全认证
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }
    
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.formLogin()
		//登录页
        .loginPage("/login")
        // 设置登录验证请求地址为自定义登录页配置action （"/login/form"）
        .loginProcessingUrl("/auth/login")
        //登录成功页面
//        .defaultSuccessUrl("/hello")
        .successHandler(successHandler) // 登录成功
        .failureUrl("/login?error1").permitAll()
        .and()
        .logout().logoutUrl("/auth/logout")
        .logoutSuccessUrl("/login").permitAll()
        .deleteCookies("JSESSIONID")
        .and()
        .authorizeRequests()
        //白名单地址
        .antMatchers("/index", "/login", "/error","/register","/auth/register","/favicon.ico").permitAll()
        //其他地址需要授权
        .anyRequest()
//        .access("@rbacauthorityservice.hasPermission(request,authentication)") // RBAC 动态 url 认证
        .authenticated()//任何请求,登录后可以访问
        .and()
        .exceptionHandling()
        .accessDeniedHandler(accessDeniedHandler)
        .and()
        .sessionManagement()
        // 设置Session失效跳转页面
        .invalidSessionUrl("/login")
        // 设置最大Session数为2
        .maximumSessions(1)
        // 设置Session过期处理策略
        .expiredSessionStrategy(new SessionInformationExpiredStrategyImpl())
        .and()
        // 暂时停用csrf，否则会影响验证
        .and().csrf().disable();
		
		// 记住我
        http.rememberMe().rememberMeParameter("remember-me")
                .userDetailsService(userDetailsService).tokenValiditySeconds(300);
        
        http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
	}

}
